﻿using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Web.Profile;
using System.Web.Security;
using MyBet.Web.Resources;
using System.Net.Mail ;
using ParieurPro.DAL.DatabaseModel;
using ParieurPro.DAL;
using System.Security.Cryptography;
using System.Text;
using ParieurPro.DAL.Util;

namespace MyBet.Web.Services
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class SecurityService
    {

        #region User Management
        [OperationContract]
        /// <summary>
        /// Returns current user
        /// </summary>
        /// <returns></returns>
        public UserObject LoadUser(string userName)
        {
            UserObject returnedValue = null;
            using (MyBetDBEntities dbContext = new MyBetDBEntities())
            {
                returnedValue = UserObject.LoadUser(dbContext, userName);
            }
            return returnedValue;
        }

        [OperationContract]
        /// <summary>
        /// Returns current user object
        /// </summary>
        /// <returns></returns>
        public UserObject LoadUserFromCustomContest(string userName,int customContestId)
        {
            UserObject returnedValue = null;
            using (MyBetDBEntities dbContext = new MyBetDBEntities())
            {
                returnedValue = UserObject.CopyFrom(dbContext, userName, customContestId);
            }
            return returnedValue;
        }

        [OperationContract]
        /// <summary>
        /// Reset user password and give it by email
        /// </summary>
        /// <returns></returns>
        public bool ResetUserPassword(string userName, string answer)
        {
            try
            {
                MembershipUser u = Membership.FindUsersByName(userName)[userName];
               
                string newPassword = String.Empty;
                u.UnlockUser();
                newPassword = u.ResetPassword(answer);
                MailMessage mail = new MailMessage("administrator@parieurpro.com", u.Email);
                String message = "Votre mot de passe a été réinitialisé" + Environment.NewLine;
                message += Environment.NewLine;
                message += "Login : " + userName + Environment.NewLine;
                message += Environment.NewLine;
                message += "Nouveau mot de passe : " + newPassword + Environment.NewLine;
                message += Environment.NewLine;
                message += "Bons pronostics," + Environment.NewLine;
                message += "Equipe ParieurPro.com";
                mail.Subject = "[ParieurPro] Réinitialisation mot de passe";
                mail.Body = message;
                mail.IsBodyHtml = false;
                SmtpClient smtp = new SmtpClient();
                smtp.Send(mail);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex);
                return false;
            }

            return true;
        }

        [OperationContract]
        /// Returns number of users online
        /// </summary>
        /// <returns></returns>
        public Int32 GetNumberOfUsersOnline()
        {
           return Membership.GetNumberOfUsersOnline();
        }

        [OperationContract]
        /// Return question for a given user to change or reset his password
        /// </summary>
        /// <returns></returns>
        public String GetPasswordQuestion(string login, string email)
        {
            String returnValue = null;
            using (MyBetDBEntities dbContext = new MyBetDBEntities())
            {
                UserObject user = UserObject.GetUserFromLoginAndEmail(dbContext, login, email);
                if (user != null)
                {
                    returnValue = user.PasswordQuestion;
                }
            }

            return returnValue;
        }

        /// <summary>/// Calculates SHA1 hash
        /// </summary>
        /// <param name="text">input string</param>
        /// <param name="enc">Character encoding</param>
        /// <returns>SHA1 hash</returns>
        private string CalculateSHA1(string text, Encoding enc)
        {
            byte[] buffer = enc.GetBytes(text);
            SHA1CryptoServiceProvider cryptoTransformSHA1 = new SHA1CryptoServiceProvider();
            string hash = BitConverter.ToString(cryptoTransformSHA1.ComputeHash(buffer)).Replace("-", "");
            return hash;
        }

        [OperationContract]
        /// <summary>
        /// Change user password and give it by email
        /// </summary>
        /// <returns></returns>
        public bool ChangeUserPassword(string userName, string oldPassword, string newPassword)
        {
            //
            try
            {
                MembershipUser u = Membership.FindUsersByName(userName)[userName];
                u.UnlockUser();
                if (u.ChangePassword(oldPassword, newPassword))
                {
                    MailMessage mail = new MailMessage("administrator@parieurpro.com", u.Email);
                    String message = "Votre mot de passe a été modifié avec succès" + Environment.NewLine;
                    message += Environment.NewLine;
                    message += "Login : " + userName + Environment.NewLine;
                    message += Environment.NewLine;
                    message += "Nouveau mot de passe : " + newPassword + Environment.NewLine;
                    message += Environment.NewLine;
                    message += "Bons pronostics," + Environment.NewLine;
                    message += "Equipe ParieurPro.com";
                    mail.Subject = "[ParieurPro] Changement de mot de passe";
                    mail.Body = message;
                    mail.IsBodyHtml = false;
                    SmtpClient smtp = new SmtpClient();
                    smtp.Send(mail);
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex);
                return false;
            }

            return true;
        }

#endregion

#region Contest Management

        /// <summary>
        /// Création d'un tournoi personnalisé
        /// </summary>
        /// <param name="userId">Identifiant unique de l'administrateur</param>
        /// <param name="userName">Login de l'administrateur</param>
        /// <param name="contestId">Identifiant du tournoi à personnaliser</param>
        /// <param name="displayName">Nom du tournoi personnalisé</param>
        /// <param name="code">Code du tournoi pour valider sa création</param>
        /// <param name="password">Mot de passe du tournoi</param>
        /// <param name="myFault">Dernière erreur rencontrée</param>
        /// <returns></returns>
        [OperationContract]
        public bool CreateCustomContest(Guid userId, string userName, int contestId, string displayName, string code, string password, out ParieurProFault myFault)
        {
            string expectedPassword;
            myFault = null;
            try
            {
                MembershipUser u = Membership.FindUsersByName(userName)[userName];
                if (u == null)
                {
                    myFault = new ParieurProFault() { FaultType = "Exception", Message = "Utilisateur inconnu" };
                    return false;
                }
                // Génération du mot de passe et envoi par mail
                expectedPassword = CalculateSHA1(userName + DateTime.UtcNow.Year.ToString() + displayName + DateTime.UtcNow.Month.ToString(), Encoding.ASCII);
                if (code != expectedPassword)
                { 
                    // Mot de passe invalide
                    myFault = new ParieurProFault() { FaultType = "Exception", Message = "Mot de passe invalide ou expiré, veuillez en générer un nouveau svp." };
                    return false;
                }
                // Création du tournoi
                using (MyBetDBEntities dbContext = new MyBetDBEntities())
                {
                    CustomContestObject.CreateContestStatus status;
                    string encryptedPassword = CalculateSHA1(password,Encoding.ASCII);
                    // On vérifie si le tournoi n'existe pas déjà
                    int contestid = CustomContestObject.GetCustomContestsIdFromName(dbContext, displayName);
                    if (contestid != 0)
                    {
                        myFault = new ParieurProFault() { FaultType = "Exception", Message = "Un tournoi a déjà été créé avec ce nom." };
                        return false;
                    }

                    status = CustomContestObject.CreateCustomContest(dbContext, userId, contestId, displayName, encryptedPassword);
                    switch (status)
                    {
                        case CustomContestObject.CreateContestStatus.Success:
                            return true;
                        case CustomContestObject.CreateContestStatus.GeneralFailure:
                            myFault = new ParieurProFault() { FaultType = "Exception", Message = "Echec de création du tournoi." };
                            return false;
                        default:
                            myFault = new ParieurProFault() { FaultType = "Exception", Message = "Echec de création du tournoi. Internal error." };
                            return false;
                    }
                }
            }
            catch (Exception ex)
            {
                myFault = new ParieurProFault() { FaultType = "Exception", Message = ex.Message };
                return false;
            }
        }

        [OperationContract]
        /// <summary>
        /// Envoi le mot de passe du tournoi par email
        /// </summary>
        /// <returns></returns>
        public bool GetContestPassword(string userName, string contestName, out ParieurProFault myFault)
        {
            int contestid;
            string password;

            myFault = null;
            try
            {
                MembershipUser u = Membership.FindUsersByName(userName)[userName];
                if (u == null)
                {
                    myFault = new ParieurProFault() { FaultType = "Exception", Message = "Utilisateur inconnu" };
                    return false;
                }

                using (MyBetDBEntities dbContext = new MyBetDBEntities())
                {
                    // On vérifie si le tournoi n'existe pas déjà
                    contestid = CustomContestObject.GetCustomContestsIdFromName(dbContext, contestName);
                    if (contestid != 0)
                    {
                        myFault = new ParieurProFault() { FaultType = "Exception", Message = "Un tournoi existe déjà avec ce nom. Veuillez en choisir un autre." };
                        return false;
                    }
                    // Génération du mot de passe et envoi par mail
                    password = CalculateSHA1(userName + DateTime.UtcNow.Year.ToString() + contestName + DateTime.UtcNow.Month.ToString(), Encoding.ASCII);

                    // Envoi par mail
                    MailMessage mail = new MailMessage("administrator@parieurpro.com", u.Email);
                    String message = "Mot de passe du tournoi " + contestName;
                    message += Environment.NewLine;
                    message += "Mot de passe : " + password + Environment.NewLine;
                    message += Environment.NewLine;
                    message += "Bons pronostics," + Environment.NewLine;
                    message += "Equipe ParieurPro.com";
                    mail.Subject = "[ParieurPro] Mot de passe du tournoi " + contestName;
                    mail.Body = message;
                    mail.IsBodyHtml = false;
                    SmtpClient smtp = new SmtpClient();
                    smtp.Send(mail);

                }
            }
            catch (Exception ex)
            {
                myFault = new ParieurProFault() { FaultType = "Exception", Message = ex.Message };
                return false;
            }

            return true;
        }

        [OperationContract]
        /// Return question for a given user to change or reset his password
        /// </summary>
        /// <returns></returns>
        public bool RequestContestCodeByEmail(string userName, string lowerEmail, string customContestName, out ParieurProFault myFault)
        {
            MembershipUser currentUser = Membership.FindUsersByName(userName)[userName];
            myFault = null;
            return true;
        }

#endregion


    }
}
